// Package gen
// @Author: zhangdi
// @File: get_field_info
// @Version: 1.0.0
// @Date: 2023/11/26 20:53
package gen

import (
	"reflect"
	"server/application/constant/enums"
	"strings"
)

// GetFieldList 获取构造字段信息列表
func GetFieldList(entityType reflect.Type, entityInfo *EntityInfo) []*FieldInfo {
	newFieldList := make([]*FieldInfo, 0)
	for i := 0; i < entityType.NumField(); i++ {
		field := entityType.Field(i)
		FieldInfo := GetFieldByEntityInfo(entityInfo, field.Name)

		if FieldInfo == nil { //首次创建实体json文件或者现有json文件中没有该字段的配置信息，则读取默认的
			FieldInfo = GetDefaultFieldInfo(field) //读构建一个默认的配置并使用该配置
		}
		if FieldInfo.DtoConfig.JsonName == "-" {
			//转下划线
			FieldInfo.DtoConfig.JsonName = NameToLine(field.Name)
		}
		FieldInfo.TypeGo = field.Type.String() //更新类型字符串
		//数组（一对多或者多对多）
		if strings.Contains(FieldInfo.TypeGo, "sentity.") {

			continue //模型类型不参与生产
			// if field.Type.Kind() == reflect.Slice {
			// 	FieldInfo.TypeGo = "[]" + strings.ReplaceAll(FieldInfo.TypeGo, "[]sentity.", "")
			// 	FieldInfo.TypeGo += "Info"
			// }
		}

		//更新字段名，取实体gorm.column属性
		dbTagName := getColumnName(entityType.Field(i).Tag.Get("gorm"), field.Name)

		FieldInfo.DbFieldName = dbTagName
		newFieldList = append(newFieldList, FieldInfo)
	}
	return newFieldList
}

// GetDefaultFieldInfo 获取字段的默认配置参数（新字段是调用）
func GetDefaultFieldInfo(field reflect.StructField) *FieldInfo {
	//将tag中的数据存入map中
	tagGorm := field.Tag.Get("gorm")
	tagJson := field.Tag.Get("json")
	tagGormMap := ParseTagToMap(tagGorm)

	if field.Name == "IsLink" {
		println(field.Name)
	}

	//如果没配置json标签，默认为非必填
	fieldFormRequire := true
	if strings.Contains(tagJson, "omitempty") {
		//如果配置了json标签，但是omitempty没有配置，则说明该项是必填。
		fieldFormRequire = false
	}

	//json标签名
	tagJsonArr := strings.Split(tagJson, ",")
	fieldTagJsonName := NameToLine(field.Name)      //默认取字段名下划线命名法
	if len(tagJsonArr) > 0 && tagJsonArr[0] != "" { //如果自定义json标签了则取自定义的
		fieldTagJsonName = tagJsonArr[0]
	}

	//是否是主键字段
	primarykey := false
	pkFieldName := ""
	if strings.Contains(strings.ToLower(tagGorm), "primarykey") {
		// 如果tagGorm中包含"primarykey"子串（不区分大小写）
		primarykey = true //如果是主键，则为删除dto
		pkFieldName = field.Name
	}

	//设置默认的表单类型
	formType := enums.FormTypeInput
	typeString := field.Type.String()
	if typeString == "bool" {
		formType = enums.FormTypeSwitch
	}
	if typeString == "int" || typeString == "int8" || typeString == "int16" || typeString == "int32" || typeString == "int64" {
		formType = enums.FormTypeInputNumber // field的类型是整型
	}
	if primarykey {
		//主键隐藏，不显示
		formType = enums.FormTypeHidden
	}

	//是否为创建dto
	isCreateDto := !primarykey
	isUpdateDto := true
	isInfoDto := true
	isDeleteDto := primarykey
	if field.Name == "CreatedAt" || field.Name == "UpdatedAt" || field.Name == "DeletedAt" {
		isCreateDto = false
		isUpdateDto = false
		isDeleteDto = false
	}
	if field.Name == "DeletedAt" {
		isInfoDto = false
	}

	DefaultFieldInfo := &FieldInfo{
		IsPK:        primarykey,
		PkFieldName: pkFieldName, //主键字段名称
		FieldName:   field.Name,  //字段名称
		//DbFieldName:   getColumnName(tagGorm, field.Name),
		Label:         GetMapValDefault(tagGormMap, "comment", field.Name), //label
		FieldLineName: NameToLine(field.Name),                              //字段下划线命名
		TypeGo:        "",                                                  //go类型
		EditConfig: FieldEditConfig{
			FormType:     formType,
			FormOptions:  nil,
			FormRequired: fieldFormRequire,
		},
		ColsConfig: FieldColumnConfig{
			Tag:    false,
			IsShow: true,
			Width:  nil,
			Align:  "",
		},
		DtoConfig: FieldDtoConfig{
			JsonName: fieldTagJsonName,
			IsCreate: isCreateDto,
			IsInfo:   isInfoDto,
			IsUpdate: isUpdateDto,
			IsDelete: isDeleteDto,
		},
		SearchConfig: FieldSearchConfig{
			FormType:     enums.FormSearchTypeInput,
			Props:        nil,
			Order:        0,
			Span:         0,
			Offset:       0,
			DefaultValue: nil,
		},
	}
	return DefaultFieldInfo
}

// 获取字段名
func getColumnName(tagGorm string, fieldName string) string {

	// 查找 "column:" 的索引位置
	if idx := strings.Index(tagGorm, "column:"); idx != -1 {
		// 截取 "column:" 后面的内容
		tag := tagGorm[idx+7:]
		// 查找 ";" 的索引位置，用于截取多余的内容
		if idx := strings.Index(tag, ";"); idx != -1 {
			tag = tag[:idx]
		}
		return tag
	}

	return NameToLine(fieldName) //直接使用下划线命名法作为字段名
}
